﻿using MuseLibrary;
using MuseUI.ObservableData;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace MuseUI
{
    public partial class MainView : Form
    {
        public MainView(MainPresenter presenter)
        {
            InitializeComponent();

            _presenter = presenter;
            SetupControlsForUserContext();

            optionsGridView.AutoGenerateColumns = false;
            optionsGridView.DataSource = _presenter.ChartingOptions;
        }

        private void SetupControlsForUserContext()
        {
            if (_presenter.UserContext.NotchFrequency == 50)
                notchFrequency50HzStripMenuItem.Checked = true;
            else
                notchFrequency60HzStripMenuItem.Checked = true;
        }


        private void OnDiscoverToolStripMenuItemClick(object sender, EventArgs e)
        {
            _presenter.DiscoverDevices();
        }

        internal void UpdateConnectionStatus(string statusText, Color statusColour)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new MethodInvoker(() => UpdateConnectionStatus(statusText, statusColour)));
                return;
            }

            connectionStatusLabel.Text = statusText;
            connectionStatusLabel.BackColor = statusColour;
        }

        internal void UpdatePacketsCount(int count)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new MethodInvoker(() => UpdatePacketsCount(count)));
                return;
            }

            packetCounterLabel.Text = String.Format("Packets received: {0}", count);
        }

        internal void UpdateBatteryPercent(Double batteryPercent)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new MethodInvoker(() => UpdateBatteryPercent(batteryPercent)));
                return;
            }

            batteryLabel.Text = String.Format("Battery: {0:P1}", batteryPercent);
        }

        internal void UpdateChart(List<Series> allSeries)
        {
            MainChart.Series.Clear();
            foreach (var series in allSeries)
                MainChart.Series.Add(series);
        }

        private void OnFormClosing(object sender, FormClosingEventArgs e)
        {
            _presenter.CloseMuseConnection();
        }

        private void OnConnectToolStripMenuItemClick(object sender, EventArgs e)
        {
            _presenter.Connect();
        }

        private MainPresenter _presenter;

        internal void BindChartingOptions()
        {
            optionsGridView.DataSource = _presenter.ChartingOptions;
        }

        private void OnOptionsGridViewCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex != -1 && e.ColumnIndex == colourCol.Index)
            {
                e.Paint(e.CellBounds, DataGridViewPaintParts.Background);
                e.Paint(e.CellBounds, DataGridViewPaintParts.Border);
                var squareSize = (e.CellBounds.Width < e.CellBounds.Height) ? e.CellBounds.Width : e.CellBounds.Height;
                var square = new Rectangle(e.CellBounds.X + 5, e.CellBounds.Y + 5, squareSize - 12, squareSize - 12);
                var observableDataOption = (ObservableDataOption)_presenter.ChartingOptions[e.RowIndex];
                e.Graphics.FillRectangle(new SolidBrush(observableDataOption.SeriesColour), square);
                e.Graphics.DrawRectangle(Pens.Black, square);
                e.Handled = true;
            }

            if (e.ColumnIndex == recordCol.Index)
            {
                if (e.RowIndex == -1)
                {
                    e.Paint(e.CellBounds, DataGridViewPaintParts.Background);
                    e.Paint(e.CellBounds, DataGridViewPaintParts.Border);
                    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    var squareSize = (e.CellBounds.Width < e.CellBounds.Height) ? e.CellBounds.Width : e.CellBounds.Height;
                    var circleRectangle = new Rectangle(e.CellBounds.X + 4, e.CellBounds.Y + 4, squareSize - 9, squareSize - 9);
                    e.Graphics.FillEllipse(Brushes.Red, circleRectangle);
                    e.Handled = true;
                }
                else if (e.RowIndex >= 4)
                {
                    e.Paint(e.CellBounds, DataGridViewPaintParts.Background);
                    e.Paint(e.CellBounds, DataGridViewPaintParts.Border);
                    e.Handled = true;
                }
            }
        }

        private void OnRecordButtonClick(object sender, EventArgs e)
        {
            _presenter.ToggleRecording();
            recordButton.Text = (_presenter.IsRecording) ? "Stop" : "Record";
        }

        private void OnOptionsGridViewCellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.RowIndex == -1 || e.RowIndex >= 4) return;



            if (e.ColumnIndex == isShownCol.Index || e.ColumnIndex == recordCol.Index)
            {
                var options = ((ObservableDataOption)_presenter.ChartingOptions[e.RowIndex]);
                if (e.ColumnIndex == isShownCol.Index)
                    options.IsShown = !options.IsShown;
                else if (e.ColumnIndex == recordCol.Index)
                    options.IsRecording = !options.IsRecording;
            }
        }

        private void OnNotchFrequencyMenuItemClick(object sender, EventArgs e)
        {
            if ((sender as ToolStripMenuItem) == notchFrequency50HzStripMenuItem)
            {
                _presenter.SetNotchFrequency(50);
                notchFrequency50HzStripMenuItem.Checked = true;
                notchFrequency60HzStripMenuItem.Checked = false;
            }
            else if ((sender as ToolStripMenuItem) == notchFrequency50HzStripMenuItem)
            {
                _presenter.SetNotchFrequency(60);
                notchFrequency50HzStripMenuItem.Checked = false;
                notchFrequency60HzStripMenuItem.Checked = true;
            }
        }

        private void OnMainChartMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right) return;
            MainChart.ContextMenuStrip.Items.Clear();
            var hitTest = MainChart.HitTest(e.X, e.Y);
            if (hitTest.ChartArea.Name != "Fourier")
            {
                var eeg = new ToolStripMenuItem("EEG");
                eeg.Click += (s, eArgs) => _presenter.SetMuseChartType(MuseChartType.Eeg);
                if (_presenter.SelectedMuseChartType == MuseChartType.Eeg)
                    eeg.Checked = true;

                var accelerometer = new ToolStripMenuItem("Accelerometer");
                accelerometer.Click += (s, eArgs) => _presenter.SetMuseChartType(MuseChartType.Accelerometer);
                if (_presenter.SelectedMuseChartType == MuseChartType.Accelerometer)
                    accelerometer.Checked = true;

                MainChart.ContextMenuStrip.Items.Add(eeg);
                MainChart.ContextMenuStrip.Items.Add(accelerometer);
            }
            else
            {
                for (int i = 0; i < 4; i++)
                {
                    var channel = i;
                    var fourierChannel = new ToolStripMenuItem(String.Format("Channel {0}", channel + 1));
                    fourierChannel.Click += (s, eArgs) => _presenter.SetFourierChannel(channel);
                    if (_presenter.SelectedFourierChannel == channel)
                        fourierChannel.Checked = true;

                    MainChart.ContextMenuStrip.Items.Add(fourierChannel);
                }
            }
        }

        private void OnAboutToolStripMenuItemClick(object sender, EventArgs e)
        {
            new AboutView().Show();
        }
    }
}
